<template>
  <div class="star-tracking-analyzer">
    <div class="analyzer-header">
      <h3>星点跟踪分析</h3>
      <p>上传天文照片，分析星点形状评估赤道仪跟踪精度</p>
    </div>
    
    <!-- 图片上传区域 -->
    <div 
      class="upload-area"
      :class="{ 'drag-over': isDragging }"
      @dragover.prevent="handleDragOver"
      @dragleave.prevent="handleDragLeave"
      @drop.prevent="handleDrop"
      @click="triggerFileSelect"
    >
      <div class="upload-content">
        <div class="upload-icon">📸</div>
        <p>{{ uploadText }}</p>
        <small>支持 JPG, PNG, TIFF 格式</small>
      </div>
      <input 
        ref="fileInput" 
        type="file" 
        accept="image/jpeg,image/png,image/tiff" 
        style="display: none"
        @change="handleFileSelect"
      >
    </div>
    
    <!-- 分析进度 -->
    <div v-if="analysisProgress > 0 && analysisProgress < 100" class="progress-container">
      <div class="progress-bar">
        <div class="progress-fill" :style="{ width: analysisProgress + '%' }"></div>
      </div>
      <p>{{ analysisProgress }}% - {{ currentAnalysisStep }}</p>
    </div>
    
    <!-- 加载中 -->
    <div v-if="isAnalyzing" class="loading-container">
      <div class="loading-spinner"></div>
      <p>正在分析星点数据...</p>
    </div>
    
    <!-- 错误提示 -->
    <div v-if="errorMessage" class="error-message">
      <div class="error-icon">❌</div>
      <p>{{ errorMessage }}</p>
    </div>
    
    <!-- 分析结果 -->
    <div v-if="analysisResults && !isAnalyzing" class="analysis-results">
      <div class="results-header">
        <h4>分析结果</h4>
        <div class="tracking-score" :class="getScoreClass(trackingScore)">
          <span class="score-number">{{ trackingScore }}/100</span>
          <span class="score-text">{{ getScoreText(trackingScore) }}</span>
        </div>
      </div>
      
      <div class="results-grid">
        <!-- 原始图像和分析覆盖图 -->
        <div class="image-section">
          <div class="image-comparison">
            <div class="image-container">
              <h5>原始图像</h5>
              <img :src="originalImageUrl" alt="原始图像" class="analyzed-image">
            </div>
            <div class="image-container">
              <h5>星点分析</h5>
              <canvas ref="analysisCanvas" class="analyzed-image"></canvas>
            </div>
          </div>
          
          <!-- 放大的星点示例 -->
          <div class="star-samples" v-if="starSamples.length > 0">
            <h5>星点示例</h5>
            <div class="samples-grid">
              <div 
                v-for="(sample, index) in starSamples" 
                :key="index" 
                class="star-sample"
                :class="{ 'elongated': sample.elongation > starElongationThreshold }"
              >
                <canvas :ref="el => setSampleCanvasRef(el, index)" class="sample-canvas"></canvas>
                <p class="sample-info">
                  拉长度: {{ sample.elongation.toFixed(2) }}
                  <span v-if="sample.elongation > starElongationThreshold" class="warning">⚠️</span>
                </p>
              </div>
            </div>
          </div>
        </div>
        
        <!-- 详细分析数据 -->
        <div class="data-section">
          <!-- 基本分析数据 -->
          <div class="data-card">
            <h5>分析概览</h5>
            <div class="data-item">
              <span class="label">检测到的星点数量:</span>
              <span class="value">{{ detectedStars }}</span>
            </div>
            <div class="data-item">
              <span class="label">平均星点拉长度:</span>
              <span class="value" :class="{ warning: averageElongation > starElongationThreshold }">
                {{ averageElongation.toFixed(2) }}
              </span>
            </div>
            <div class="data-item">
              <span class="label">不规则星点比例:</span>
              <span class="value" :class="{ warning: irregularStarsPercentage > 30 }">
                {{ irregularStarsPercentage.toFixed(1) }}%
              </span>
            </div>
            <div class="data-item">
              <span class="label">星点分布均匀度:</span>
              <span class="value">{{ starDistributionScore.toFixed(1) }}/10</span>
            </div>
          </div>
          
          <!-- 跟踪问题分析 -->
          <div class="data-card" v-if="trackingIssues.length > 0">
            <h5>跟踪问题分析</h5>
            <ul class="issue-list">
              <li v-for="(issue, index) in trackingIssues" :key="index" class="issue-item">
                <span class="issue-icon">{{ getIssueIcon(issue.type) }}</span>
                <span class="issue-text">{{ issue.description }}</span>
              </li>
            </ul>
          </div>
          
          <!-- 改进建议 -->
          <div class="data-card" v-if="improvementSuggestions.length > 0">
            <h5>改进建议</h5>
            <ul class="suggestion-list">
              <li v-for="(suggestion, index) in improvementSuggestions" :key="index" class="suggestion-item">
                <span class="suggestion-icon">💡</span>
                <span class="suggestion-text">{{ suggestion }}</span>
              </li>
            </ul>
          </div>
        </div>
      </div>
      
      <!-- 操作按钮 -->
      <div class="action-buttons">
        <button @click="clearAnalysis" class="clear-button">清除分析</button>
        <button @click="downloadReport" class="download-button">下载报告</button>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, onMounted, nextTick } from 'vue'

export default {
  name: 'StarTrackingAnalyzer',
  setup() {
    // 文件上传相关状态
    const fileInput = ref(null)
    const isDragging = ref(false)
    const uploadText = ref('拖拽天文照片到此处或点击上传')
    
    // 分析相关状态
    const isAnalyzing = ref(false)
    const analysisProgress = ref(0)
    const currentAnalysisStep = ref('')
    const errorMessage = ref('')
    
    // 图像数据
    const selectedFile = ref(null)
    const originalImageUrl = ref('')
    const analysisCanvas = ref(null)
    const sampleCanvasRefs = ref([])
    
    // 分析结果
    const analysisResults = ref(null)
    const detectedStars = ref(0)
    const averageElongation = ref(0)
    const irregularStarsPercentage = ref(0)
    const starDistributionScore = ref(0)
    const starSamples = ref([])
    const trackingScore = ref(0)
    const trackingIssues = ref([])
    const improvementSuggestions = ref([])
    
    // 配置参数
    const starElongationThreshold = 1.3 // 星点拉长阈值，超过此值视为不规则
    const minStarSize = 2 // 最小星点像素
    const maxStarSize = 20 // 最大星点像素
    
    // 处理拖拽事件
    const handleDragOver = (event) => {
      event.preventDefault()
      isDragging.value = true
      uploadText.value = '释放以分析照片'
    }
    
    const handleDragLeave = (event) => {
      event.preventDefault()
      isDragging.value = false
      uploadText.value = '拖拽天文照片到此处或点击上传'
    }
    
    const handleDrop = (event) => {
      event.preventDefault()
      isDragging.value = false
      uploadText.value = '拖拽天文照片到此处或点击上传'
      
      const files = event.dataTransfer.files
      if (files.length) {
        processImage(files[0])
      }
    }
    
    const triggerFileSelect = () => {
      fileInput.value.click()
    }
    
    const handleFileSelect = (event) => {
      const files = event.target.files
      if (files.length) {
        processImage(files[0])
      }
    }
    
    // 处理图像文件
    const processImage = (file) => {
      // 重置状态
      errorMessage.value = ''
      analysisResults.value = null
      analysisProgress.value = 0
      
      // 检查文件类型
      const validTypes = ['image/jpeg', 'image/png', 'image/tiff']
      if (!validTypes.includes(file.type)) {
        errorMessage.value = '不支持的文件类型，请上传JPG、PNG或TIFF格式的图片'
        return
      }
      
      // 检查文件大小
      if (file.size > 15 * 1024 * 1024) { // 15MB限制
        errorMessage.value = '文件太大，建议上传小于15MB的图片以获得更好的性能'
        return
      }
      
      selectedFile.value = file
      
      // 创建预览
      const reader = new FileReader()
      reader.onload = (e) => {
        originalImageUrl.value = e.target.result
        
        // 开始分析
        setTimeout(() => {
          analyzeImage(e.target.result)
        }, 500)
      }
      reader.readAsDataURL(file)
    }
    
    // 设置样本canvas引用
    const setSampleCanvasRef = (el, index) => {
      if (el) {
        sampleCanvasRefs.value[index] = el
      }
    }
    
    // 分析图像
    const analyzeImage = async (imageUrl) => {
      isAnalyzing.value = true
      analysisProgress.value = 10
      currentAnalysisStep.value = '加载图像...'
      
      try {
        // 加载图像
        const img = await loadImage(imageUrl)
        
        // 调整分析进度
        updateProgress(20, '预处理图像...')
        
        // 创建分析canvas
        const canvas = analysisCanvas.value
        const ctx = canvas.getContext('2d')
        
        // 调整canvas尺寸
        const maxDimension = 800 // 最大处理尺寸
        let width = img.width
        let height = img.height
        
        if (width > height && width > maxDimension) {
          height = Math.round((height * maxDimension) / width)
          width = maxDimension
        } else if (height > maxDimension) {
          width = Math.round((width * maxDimension) / height)
          height = maxDimension
        }
        
        canvas.width = width
        canvas.height = height
        
        // 绘制图像
        ctx.drawImage(img, 0, 0, width, height)
        
        // 获取图像数据
        updateProgress(30, '提取图像数据...')
        const imageData = ctx.getImageData(0, 0, width, height)
        const data = imageData.data
        
        // 检测星点
        updateProgress(40, '检测星点...')
        const stars = detectStars(data, width, height)
        detectedStars.value = stars.length
        
        // 分析星点形状
        updateProgress(60, '分析星点形状...')
        const analyzedStars = analyzeStarShapes(stars, data, width)
        
        // 计算统计数据
        updateProgress(70, '计算统计数据...')
        calculateStatistics(analyzedStars)
        
        // 生成星点样本
        updateProgress(80, '生成星点样本...')
        generateStarSamples(analyzedStars, img, width, height)
        
        // 绘制分析结果
        updateProgress(90, '绘制分析结果...')
        drawAnalysisResults(ctx, analyzedStars, width, height)
        
        // 生成报告
        updateProgress(95, '生成分析报告...')
        generateTrackingReport(analyzedStars)
        
        // 完成分析
        updateProgress(100, '分析完成')
        analysisResults.value = {
          detectedStars: detectedStars.value,
          averageElongation: averageElongation.value,
          irregularStarsPercentage: irregularStarsPercentage.value,
          trackingScore: trackingScore.value,
          timestamp: new Date().toISOString()
        }
        
        // 等待所有星点样本绘制完成
        await nextTick()
        
      } catch (error) {
        console.error('图像分析错误:', error)
        errorMessage.value = '分析过程中发生错误，请重试'
      } finally {
        isAnalyzing.value = false
      }
    }
    
    // 加载图像
    const loadImage = (url) => {
      return new Promise((resolve, reject) => {
        const img = new Image()
        img.onload = () => resolve(img)
        img.onerror = reject
        img.src = url
      })
    }
    
    // 更新进度
    const updateProgress = (progress, step) => {
      analysisProgress.value = progress
      currentAnalysisStep.value = step
    }
    
    // 检测星点（简化实现）
    const detectStars = (data, width, height) => {
      const stars = []
      const visited = new Array(width * height).fill(false)
      const threshold = 180 // 亮度阈值
      
      // 遍历像素检测星点
      for (let y = 1; y < height - 1; y++) {
        for (let x = 1; x < width - 1; x++) {
          const idx = (y * width + x) * 4
          const brightness = (data[idx] + data[idx + 1] + data[idx + 2]) / 3
          
          // 如果像素足够亮且未访问过
          if (brightness > threshold && !visited[y * width + x]) {
            // 进行区域生长找到星点
            const starPixels = []
            growStarRegion(x, y, width, height, data, visited, starPixels, threshold)
            
            // 只处理大小合适的星点
            if (starPixels.length >= minStarSize && starPixels.length <= maxStarSize) {
              // 计算星点中心
              let sumX = 0, sumY = 0
              for (const [px, py] of starPixels) {
                sumX += px
                sumY += py
              }
              
              const centerX = sumX / starPixels.length
              const centerY = sumY / starPixels.length
              
              stars.push({
                x: centerX,
                y: centerY,
                pixels: starPixels,
                size: starPixels.length
              })
            }
          }
        }
      }
      
      return stars
    }
    
    // 区域生长算法
    const growStarRegion = (x, y, width, height, data, visited, starPixels, threshold) => {
      const queue = [[x, y]]
      visited[y * width + x] = true
      
      while (queue.length > 0) {
        const [cx, cy] = queue.shift()
        starPixels.push([cx, cy])
        
        // 检查8个相邻像素
        for (let dy = -1; dy <= 1; dy++) {
          for (let dx = -1; dx <= 1; dx++) {
            const nx = cx + dx
            const ny = cy + dy
            
            // 检查边界
            if (nx >= 0 && nx < width && ny >= 0 && ny < height && !visited[ny * width + nx]) {
              const idx = (ny * width + nx) * 4
              const brightness = (data[idx] + data[idx + 1] + data[idx + 2]) / 3
              
              if (brightness > threshold * 0.8) { // 稍微降低邻域阈值以允许渐变
                visited[ny * width + nx] = true
                queue.push([nx, ny])
              }
            }
          }
        }
      }
    }
    
    // 分析星点形状
    const analyzeStarShapes = (stars, data, width) => {
      return stars.map(star => {
        // 计算星点边界框
        let minX = Infinity, maxX = -Infinity
        let minY = Infinity, maxY = -Infinity
        
        for (const [px, py] of star.pixels) {
          minX = Math.min(minX, px)
          maxX = Math.max(maxX, px)
          minY = Math.min(minY, py)
          maxY = Math.max(maxY, py)
        }
        
        const widthSize = maxX - minX + 1
        const heightSize = maxY - minY + 1
        
        // 计算拉长度（宽高比）
        let elongation = 1
        if (widthSize > heightSize) {
          elongation = widthSize / heightSize
        } else if (heightSize > widthSize) {
          elongation = heightSize / widthSize
        }
        
        // 判断是否为不规则星点
        const isIrregular = elongation > starElongationThreshold
        
        // 计算平均亮度
        let totalBrightness = 0
        for (const [px, py] of star.pixels) {
          const idx = (Math.floor(py) * width + Math.floor(px)) * 4
          totalBrightness += (data[idx] + data[idx + 1] + data[idx + 2]) / 3
        }
        const avgBrightness = totalBrightness / star.pixels.length
        
        return {
          ...star,
          boundingBox: { minX, maxX, minY, maxY },
          width: widthSize,
          height: heightSize,
          elongation: elongation,
          isIrregular: isIrregular,
          avgBrightness: avgBrightness
        }
      })
    }
    
    // 计算统计数据
    const calculateStatistics = (stars) => {
      if (stars.length === 0) return
      
      // 计算平均拉长度
      let totalElongation = 0
      let irregularCount = 0
      
      for (const star of stars) {
        totalElongation += star.elongation
        if (star.isIrregular) {
          irregularCount++
        }
      }
      
      averageElongation.value = totalElongation / stars.length
      irregularStarsPercentage.value = (irregularCount / stars.length) * 100
      
      // 计算星点分布均匀度（简化计算）
      calculateDistributionScore(stars)
    }
    
    // 计算星点分布均匀度
    const calculateDistributionScore = (stars) => {
      if (stars.length === 0) {
        starDistributionScore.value = 0
        return
      }
      
      // 简化的分布均匀度计算
      // 将图像分为9个区域，计算每个区域的星点数量
      const regions = Array(9).fill(0)
      const regionWidth = analysisCanvas.value.width / 3
      const regionHeight = analysisCanvas.value.height / 3
      
      for (const star of stars) {
        const regionX = Math.floor(star.x / regionWidth)
        const regionY = Math.floor(star.y / regionHeight)
        const regionIndex = regionY * 3 + regionX
        
        if (regionIndex >= 0 && regionIndex < 9) {
          regions[regionIndex]++
        }
      }
      
      // 计算标准差来衡量分布均匀度
      const avgStarsPerRegion = stars.length / 9
      let variance = 0
      
      for (const count of regions) {
        variance += Math.pow(count - avgStarsPerRegion, 2)
      }
      
      variance /= 9
      const stdDev = Math.sqrt(variance)
      
      // 将标准差转换为0-10的分数（标准差越小分数越高）
      const maxPossibleStdDev = avgStarsPerRegion * 2 // 估计的最大可能标准差
      const normalizedScore = Math.max(0, 1 - (stdDev / maxPossibleStdDev))
      starDistributionScore.value = normalizedScore * 10
    }
    
    // 生成星点样本
    const generateStarSamples = async (stars, originalImg, originalWidth, originalHeight) => {
      // 选择一些具有代表性的星点样本
      // 1. 选择最圆的几个星点
      const roundestStars = [...stars]
        .sort((a, b) => a.elongation - b.elongation)
        .slice(0, 3)
      
      // 2. 选择最不规则的几个星点
      const mostIrregularStars = [...stars]
        .sort((a, b) => b.elongation - a.elongation)
        .slice(0, 3)
      
      // 3. 合并并去重
      const selectedSamples = [...new Map([...roundestStars, ...mostIrregularStars].map(s => [s.x + ',' + s.y, s])).values()]
      
      // 限制样本数量
      const finalSamples = selectedSamples.slice(0, 6)
      starSamples.value = finalSamples
      
      // 绘制星点样本
      await nextTick()
      drawStarSamples(finalSamples, originalImg, originalWidth, originalHeight)
    }
    
    // 绘制星点样本
    const drawStarSamples = (samples, originalImg, originalWidth, originalHeight) => {
      samples.forEach((sample, index) => {
        const canvas = sampleCanvasRefs.value[index]
        if (!canvas) return
        
        const ctx = canvas.getContext('2d')
        canvas.width = 100
        canvas.height = 100
        
        // 计算缩放比例
        const scaleX = canvas.width / 100 // 100x100像素的样本区域
        const scaleY = canvas.height / 100
        
        // 计算源图像中的裁剪区域（以星点为中心，50x50像素）
        const cropSize = 50
        const x = Math.max(0, sample.x - cropSize / 2)
        const y = Math.max(0, sample.y - cropSize / 2)
        
        // 绘制裁剪的星点区域
        ctx.drawImage(
          originalImg,
          x * (originalWidth / analysisCanvas.value.width),
          y * (originalHeight / analysisCanvas.value.height),
          cropSize * (originalWidth / analysisCanvas.value.width),
          cropSize * (originalHeight / analysisCanvas.value.height),
          0, 0, canvas.width, canvas.height
        )
        
        // 绘制边框标记不规则星点
        if (sample.isIrregular) {
          ctx.strokeStyle = '#ff6b6b'
          ctx.lineWidth = 2
          ctx.strokeRect(1, 1, canvas.width - 2, canvas.height - 2)
        }
      })
    }
    
    // 绘制分析结果
    const drawAnalysisResults = (ctx, stars, width, height) => {
      // 重新绘制原始图像（稍微降低透明度）
      ctx.globalAlpha = 0.8
      ctx.drawImage(analysisCanvas.value, 0, 0)
      ctx.globalAlpha = 1
      
      // 绘制星点标记
      stars.forEach(star => {
        // 为不规则星点绘制红色边框，规则星点绘制绿色边框
        ctx.strokeStyle = star.isIrregular ? '#ff6b6b' : '#4ecdc4'
        ctx.lineWidth = 1
        ctx.beginPath()
        ctx.rect(
          star.boundingBox.minX - 1,
          star.boundingBox.minY - 1,
          star.width + 2,
          star.height + 2
        )
        ctx.stroke()
        
        // 绘制星点中心
        ctx.fillStyle = star.isIrregular ? '#ff6b6b' : '#4ecdc4'
        ctx.beginPath()
        ctx.arc(star.x, star.y, 2, 0, Math.PI * 2)
        ctx.fill()
      })
      
      // 绘制图例
      drawLegend(ctx, width, height)
    }
    
    // 绘制图例
    const drawLegend = (ctx, width, height) => {
      // 图例背景
      ctx.fillStyle = 'rgba(10, 10, 42, 0.8)'
      ctx.fillRect(width - 120, 10, 110, 60)
      
      // 绘制规则星点标记
      ctx.strokeStyle = '#4ecdc4'
      ctx.lineWidth = 1
      ctx.strokeRect(width - 110, 20, 10, 10)
      ctx.fillStyle = '#4ecdc4'
      ctx.beginPath()
      ctx.arc(width - 105, 25, 2, 0, Math.PI * 2)
      ctx.fill()
      
      // 规则星点文字
      ctx.fillStyle = '#ffffff'
      ctx.font = '12px Arial'
      ctx.fillText('规则星点', width - 95, 30)
      
      // 绘制不规则星点标记
      ctx.strokeStyle = '#ff6b6b'
      ctx.lineWidth = 1
      ctx.strokeRect(width - 110, 40, 10, 10)
      ctx.fillStyle = '#ff6b6b'
      ctx.beginPath()
      ctx.arc(width - 105, 45, 2, 0, Math.PI * 2)
      ctx.fill()
      
      // 不规则星点文字
      ctx.fillStyle = '#ffffff'
      ctx.fillText('不规则星点', width - 95, 50)
    }
    
    // 生成跟踪报告
    const generateTrackingReport = (stars) => {
      // 计算跟踪评分
      calculateTrackingScore()
      
      // 分析跟踪问题
      analyzeTrackingIssues(stars)
      
      // 生成改进建议
      generateImprovementSuggestions()
    }
    
    // 计算跟踪评分
    const calculateTrackingScore = () => {
      // 基于多个因素计算综合评分
      let score = 100
      
      // 基于不规则星点百分比扣分
      if (irregularStarsPercentage.value > 10) {
        const excessPercentage = Math.max(0, irregularStarsPercentage.value - 10)
        score -= excessPercentage * 2 // 每超出1%扣2分
      }
      
      // 基于平均拉长度扣分
      if (averageElongation.value > 1.2) {
        const excessElongation = Math.max(0, averageElongation.value - 1.2)
        score -= excessElongation * 25 // 每超出0.1扣2.5分
      }
      
      // 基于星点分布均匀度调整分数
      score += (starDistributionScore.value - 5) // 如果分布好，最多加5分
      
      // 确保分数在0-100范围内
      trackingScore.value = Math.max(0, Math.min(100, Math.round(score)))
    }
    
    // 分析跟踪问题
    const analyzeTrackingIssues = (stars) => {
      const issues = []
      
      // 检查不规则星点比例
      if (irregularStarsPercentage.value > 30) {
        issues.push({
          type: 'elongation',
          description: '检测到大量拉长的星点，可能存在严重的跟踪误差'
        })
      } else if (irregularStarsPercentage.value > 15) {
        issues.push({
          type: 'minor_elongation',
          description: '存在一些拉长的星点，跟踪精度有改进空间'
        })
      }
      
      // 检查是否有方向性模式
      const directionPattern = detectDirectionalPattern(stars)
      if (directionPattern) {
        issues.push({
          type: 'directional',
          description: `星点拉长呈现${directionPattern}方向的趋势，可能是极轴校准不准确或跟踪速度不匹配`
        })
      }
      
      // 检查星点分布
      if (starDistributionScore.value < 4) {
        issues.push({
          type: 'distribution',
          description: '星点分布不均匀，可能是由于视场中有亮源导致的跟踪误差或图像处理问题'
        })
      }
      
      trackingIssues.value = issues
    }
    
    // 检测星点拉长方向模式
    const detectDirectionalPattern = (stars) => {
      const irregularStars = stars.filter(s => s.isIrregular)
      if (irregularStars.length < 10) return null
      
      // 统计拉长方向
      const horizontalCount = irregularStars.filter(s => s.width > s.height).length
      const verticalCount = irregularStars.filter(s => s.height > s.width).length
      const directionRatio = Math.max(horizontalCount, verticalCount) / irregularStars.length
      
      if (directionRatio > 0.7) { // 如果70%以上的不规则星点朝同一方向
        return horizontalCount > verticalCount ? '水平' : '垂直'
      }
      
      return null
    }
    
    // 生成改进建议
    const generateImprovementSuggestions = () => {
      const suggestions = []
      
      // 基于跟踪评分提供一般性建议
      if (trackingScore.value < 60) {
        suggestions.push('强烈建议重新校准极轴，这可能是跟踪精度差的主要原因')
        suggestions.push('检查赤道仪的平衡状态，确保赤经和赤纬轴都已正确平衡')
        suggestions.push('考虑缩短曝光时间或使用导星系统')
      } else if (trackingScore.value < 80) {
        suggestions.push('建议微调极轴校准，以提高跟踪精度')
        suggestions.push('检查并更新赤道仪的固件，确保使用最新版本')
        suggestions.push('考虑在拍摄时使用自动导星系统')
      }
      
      // 基于不规则星点比例的建议
      if (irregularStarsPercentage.value > 20) {
        suggestions.push('尝试降低ISO值并延长曝光时间，配合导星使用')
        suggestions.push('检查三脚架的稳定性，确保没有振动')
        suggestions.push('考虑使用更高精度的赤道仪或增加平衡权重')
      }
      
      // 检查是否有特定方向的拉长
      const directionPattern = detectDirectionalPattern(stars.value)
      if (directionPattern === '水平') {
        suggestions.push('水平方向的星点拉长可能表明极轴高度调整不准确，建议重新校准')
      } else if (directionPattern === '垂直') {
        suggestions.push('垂直方向的星点拉长可能表明极轴方位角调整不准确或存在齿轮间隙')
      }
      
      // 如果没有具体问题，提供一般性建议
      if (suggestions.length === 0) {
        suggestions.push('跟踪精度良好！可以尝试更长时间的曝光或更暗的天体')
        suggestions.push('考虑使用自动导星系统进一步提高长时间曝光的质量')
        suggestions.push('定期维护赤道仪，清洁齿轮和轴承以保持最佳性能')
      }
      
      improvementSuggestions.value = suggestions
    }
    
    // 获取评分等级
    const getScoreClass = (score) => {
      if (score >= 90) return 'excellent'
      if (score >= 75) return 'good'
      if (score >= 60) return 'fair'
      return 'poor'
    }
    
    // 获取评分文本
    const getScoreText = (score) => {
      if (score >= 90) return '优秀'
      if (score >= 75) return '良好'
      if (score >= 60) return '一般'
      return '需要改进'
    }
    
    // 获取问题图标
    const getIssueIcon = (type) => {
      const icons = {
        'elongation': '🚨',
        'minor_elongation': '⚠️',
        'directional': '↗️',
        'distribution': '🔍'
      }
      return icons[type] || '❓'
    }
    
    // 清除分析结果
    const clearAnalysis = () => {
      analysisResults.value = null
      originalImageUrl.value = ''
      detectedStars.value = 0
      averageElongation.value = 0
      irregularStarsPercentage.value = 0
      starDistributionScore.value = 0
      starSamples.value = []
      trackingScore.value = 0
      trackingIssues.value = []
      improvementSuggestions.value = []
      errorMessage.value = ''
      analysisProgress.value = 0
      
      // 清空canvas
      if (analysisCanvas.value) {
        const ctx = analysisCanvas.value.getContext('2d')
        ctx.clearRect(0, 0, analysisCanvas.value.width, analysisCanvas.value.height)
      }
      
      // 清空文件输入
      if (fileInput.value) {
        fileInput.value.value = ''
      }
    }
    
    // 下载分析报告
    const downloadReport = () => {
      const report = {
        generatedAt: new Date().toISOString(),
        fileName: selectedFile.value?.name || '未命名图像',
        trackingScore: trackingScore.value,
        scoreText: getScoreText(trackingScore.value),
        detectedStars: detectedStars.value,
        averageElongation: averageElongation.value,
        irregularStarsPercentage: irregularStarsPercentage.value,
        starDistributionScore: starDistributionScore.value,
        trackingIssues: trackingIssues.value,
        improvementSuggestions: improvementSuggestions.value
      }
      
      const dataStr = JSON.stringify(report, null, 2)
      const blob = new Blob([dataStr], { type: 'application/json' })
      const url = URL.createObjectURL(blob)
      
      const a = document.createElement('a')
      a.href = url
      a.download = `星点跟踪分析_${Date.now()}.json`
      document.body.appendChild(a)
      a.click()
      
      setTimeout(() => {
        document.body.removeChild(a)
        URL.revokeObjectURL(url)
      }, 0)
    }
    
    return {
      // 文件上传相关
      fileInput,
      isDragging,
      uploadText,
      
      // 分析相关
      isAnalyzing,
      analysisProgress,
      currentAnalysisStep,
      errorMessage,
      
      // 图像和结果
      originalImageUrl,
      analysisCanvas,
      analysisResults,
      detectedStars,
      averageElongation,
      irregularStarsPercentage,
      starDistributionScore,
      starSamples,
      trackingScore,
      trackingIssues,
      improvementSuggestions,
      starElongationThreshold,
      
      // 方法
      handleDragOver,
      handleDragLeave,
      handleDrop,
      triggerFileSelect,
      handleFileSelect,
      setSampleCanvasRef,
      clearAnalysis,
      downloadReport,
      getScoreClass,
      getScoreText,
      getIssueIcon
    }
  }
}
</script>

<style scoped>
.star-tracking-analyzer {
  background: rgba(10, 10, 42, 0.85);
  border-radius: 16px;
  padding: 24px;
  border: 1px solid rgba(85, 136, 255, 0.2);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}

.analyzer-header {
  text-align: center;
  margin-bottom: 24px;
}

.analyzer-header h3 {
  color: #ffffff;
  margin: 0 0 8px;
  font-size: 24px;
  font-weight: 600;
}

.analyzer-header p {
  color: rgba(255, 255, 255, 0.7);
  margin: 0;
  font-size: 14px;
}

/* 上传区域 */
.upload-area {
  border: 2px dashed rgba(85, 136, 255, 0.5);
  border-radius: 12px;
  padding: 40px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  background: rgba(85, 136, 255, 0.05);
}

.upload-area:hover {
  border-color: rgba(85, 136, 255, 0.8);
  background: rgba(85, 136, 255, 0.1);
}

.upload-area.drag-over {
  border-color: #5588ff;
  background: rgba(85, 136, 255, 0.15);
}

.upload-content .upload-icon {
  font-size: 48px;
  margin-bottom: 16px;
}

.upload-content p {
  color: #ffffff;
  margin: 0 0 8px;
  font-size: 16px;
  font-weight: 500;
}

.upload-content small {
  color: rgba(255, 255, 255, 0.5);
  font-size: 12px;
}

/* 进度条 */
.progress-container {
  margin: 24px 0;
}

.progress-bar {
  width: 100%;
  height: 8px;
  background: rgba(85, 136, 255, 0.2);
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 8px;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #5588ff, #8a55ff);
  transition: width 0.3s ease;
}

.progress-container p {
  color: rgba(255, 255, 255, 0.7);
  margin: 0;
  font-size: 14px;
  text-align: center;
}

/* 加载中 */
.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px;
}

.loading-spinner {
  width: 40px;
  height: 40px;
  border: 3px solid rgba(85, 136, 255, 0.3);
  border-radius: 50%;
  border-top-color: #5588ff;
  animation: spin 1s ease-in-out infinite;
  margin-bottom: 16px;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.loading-container p {
  color: rgba(255, 255, 255, 0.7);
  margin: 0;
}

/* 错误提示 */
.error-message {
  background: rgba(255, 107, 107, 0.1);
  border: 1px solid rgba(255, 107, 107, 0.3);
  border-radius: 8px;
  padding: 16px;
  display: flex;
  align-items: center;
  margin: 16px 0;
}

.error-icon {
  font-size: 24px;
  margin-right: 12px;
  flex-shrink: 0;
}

.error-message p {
  color: #ff6b6b;
  margin: 0;
  font-size: 14px;
}

/* 分析结果 */
.analysis-results {
  margin-top: 24px;
}

.results-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
}

.results-header h4 {
  color: #ffffff;
  margin: 0;
  font-size: 20px;
  font-weight: 600;
}

.tracking-score {
  padding: 12px 20px;
  border-radius: 24px;
  font-weight: 700;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.tracking-score.excellent {
  background: rgba(76, 205, 196, 0.2);
  border: 1px solid rgba(76, 205, 196, 0.5);
  color: #4ecdc4;
}

.tracking-score.good {
  background: rgba(85, 136, 255, 0.2);
  border: 1px solid rgba(85, 136, 255, 0.5);
  color: #5588ff;
}

.tracking-score.fair {
  background: rgba(255, 183, 77, 0.2);
  border: 1px solid rgba(255, 183, 77, 0.5);
  color: #ffb74d;
}

.tracking-score.poor {
  background: rgba(255, 107, 107, 0.2);
  border: 1px solid rgba(255, 107, 107, 0.5);
  color: #ff6b6b;
}

.score-number {
  font-size: 24px;
}

.score-text {
  font-size: 12px;
  opacity: 0.9;
}

/* 结果网格 */
.results-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  margin-bottom: 24px;
}

/* 图像部分 */
.image-section {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.image-comparison {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.image-container {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.image-container h5 {
  color: #ffffff;
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  text-align: center;
}

.analyzed-image {
  max-width: 100%;
  border-radius: 8px;
  border: 1px solid rgba(85, 136, 255, 0.3);
  background: rgba(0, 0, 0, 0.3);
}

/* 星点样本 */
.star-samples h5 {
  color: #ffffff;
  margin: 0 0 12px;
  font-size: 14px;
  font-weight: 600;
}

.samples-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.star-sample {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
}

.sample-canvas {
  width: 100%;
  max-width: 100px;
  height: auto;
  border-radius: 4px;
  border: 1px solid rgba(85, 136, 255, 0.2);
  background: rgba(0, 0, 0, 0.3);
}

.star-sample.elongated .sample-canvas {
  border-color: rgba(255, 107, 107, 0.5);
}

.sample-info {
  color: rgba(255, 255, 255, 0.7);
  margin: 0;
  font-size: 11px;
  text-align: center;
}

.sample-info .warning {
  color: #ff6b6b;
  margin-left: 2px;
}

/* 数据部分 */
.data-section {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.data-card {
  background: rgba(85, 136, 255, 0.05);
  border-radius: 8px;
  padding: 16px;
  border: 1px solid rgba(85, 136, 255, 0.1);
}

.data-card h5 {
  color: #5588ff;
  margin: 0 0 12px;
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.data-item {
  display: flex;
  justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.data-item:last-child {
  border-bottom: none;
}

.data-item .label {
  color: rgba(255, 255, 255, 0.6);
  font-size: 13px;
}

.data-item .value {
  color: #ffffff;
  font-size: 13px;
  font-weight: 500;
  text-align: right;
}

.data-item .value.warning {
  color: #ffb74d;
}

/* 问题列表 */
.issue-list,
.suggestion-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.issue-item,
.suggestion-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 0;
  font-size: 12px;
  line-height: 1.4;
}

.issue-item .issue-icon,
.suggestion-item .suggestion-icon {
  font-size: 14px;
  flex-shrink: 0;
  margin-top: 1px;
}

.issue-item .issue-text {
  color: rgba(255, 183, 77, 0.9);
}

.suggestion-item .suggestion-text {
  color: rgba(255, 255, 255, 0.8);
}

/* 操作按钮 */
.action-buttons {
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-top: 24px;
}

.clear-button,
.download-button {
  padding: 10px 24px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  border: none;
}

.clear-button {
  background: rgba(255, 255, 255, 0.1);
  color: #ffffff;
}

.clear-button:hover {
  background: rgba(255, 255, 255, 0.2);
}

.download-button {
  background: linear-gradient(135deg, #5588ff, #8a55ff);
  color: #ffffff;
}

.download-button:hover {
  opacity: 0.9;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(85, 136, 255, 0.4);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .results-grid {
    grid-template-columns: 1fr;
  }
  
  .image-comparison {
    grid-template-columns: 1fr;
  }
  
  .samples-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  
  .results-header {
    flex-direction: column;
    gap: 16px;
    text-align: center;
  }
}
</style>